/**
AbstractCustomeEntity.java
jackysoft-basic-core
2012-8-6下午5:39:40
@author 屈甲康
@QQ285799123
mailto:qujiakang@126.com
 **/
package org.jackysoft.entity.base;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;





import javax.validation.constraints.NotNull;

import org.jackysoft.annotations.Transient;
import org.jackysoft.bean.define.EntitySchemas;
import org.jackysoft.ztree.ZTreeNode;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * <pre>
 * 适合用户自定义主键，例如复合ID
 * 例如 
 *    
 *    @BID
 *    private BusinessPK  id;
 *    
 *    public class BusinessPK{
 *        
 *        
 *        String  username;
 *        
 *        String  userCode; 
 *    }
 * 用户用复杂Id定义业务Id，自己用
 * 
 * </pre>
 * */


public abstract class AbstractRootEntity implements RootEntity, Cloneable,ZtreeNodeable,SecurityLogger {

	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5502736988315730458L;
	
	protected boolean leaf;
	
	protected int sort = 0;
	
	private Map<String,String> values = Maps.newHashMap();

	
	@Override
	public void setLeaf(boolean leaf) {
		this.leaf = leaf;

	}

	@Override
	@Transient
	public boolean isLeaf() {
		return leaf;
	}

	@Override
	public void setSort(int sort) {
		this.sort = sort;
	}

	@Override
	
	@NotNull
	public int getSort() {
		return this.sort;
	}

	
	@Override
	public ZTreeNode toZtreeNode() {
		// TODO Auto-generated method stub
		return null;
	}

	
	@Override
	public String toLogger() {
		// TODO Auto-generated method stub
		return null;
	}

	
	private void mapColumn(){
			
		if(!values.isEmpty())return;
		BeanWrapper bw = new BeanWrapperImpl(this);
		    PropertyDescriptor[] pds=  bw.getPropertyDescriptors();
		    for(PropertyDescriptor p :pds){
		    	String pname = p.getName();
		    	if(this.getExclude().contains(pname))continue;
		    	Method m = p.getReadMethod();
		    	if(m==null)continue;
		    	Object val;
				try {
					val = m.invoke(this);
					if(val==null)continue;
					values.put(pname, val.toString());
				} catch (IllegalAccessException | IllegalArgumentException
						| InvocationTargetException e) {
				    continue;
				}
		    	
		    }
		
	}
	
	public FieldValue getSqlInsertMeta(){
		
		mapColumn();
		List<String> fieldstr = Lists.newArrayList();
		List<String> valuestr = Lists.newArrayList();
		int i= 0;
		for(String field:values.keySet()){
			fieldstr.add(i,field);
			valuestr.add(i,values.get(field));
			i++;
		}		
		return new FieldValue(Joiner.on(",").join(fieldstr),Joiner.on("','").join(valuestr));		
	}
	
	public String getSqlUpdateMeta(){
		mapColumn();
		List<String> fieldstr = Lists.newArrayList();
		for(String field:values.keySet()){
		    String value = values.get(field);
		    if(value==null)continue;
			fieldstr.add(String.format("%s='%s'", field,value));			
		}	
		return Joiner.on(",").join(fieldstr);
	}
	
	
	public Set<String> getExclude(){
		return Sets.newHashSet("id","class","exclude","sqlMeta");
	}
	
	
	@Override
	public Object clone() {
		try {
			ByteArrayOutputStream bout = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bout);
			out.writeObject(this);
			out.close();

			ByteArrayInputStream bin = new ByteArrayInputStream(
					bout.toByteArray());
			ObjectInputStream in = new ObjectInputStream(bin);
			Object ret = in.readObject();
			return ret;

		} catch (Exception e) {
			return null;
		}
	}

}
